package cn.songdragon.zboschina.crawler;

import java.util.Map;
import java.util.Random;

import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.songdragon.zboschina.HttpClient;
import cn.songdragon.zboschina.HttpResponse;
import cn.songdragon.zboschina.IFlightCrawler;
import cn.songdragon.zboschina.IRefererGenerator;
//import cn.songdragon.zboschina.ProxyManager;
import cn.songdragon.zboschina.exception.NoProxyException;
import cn.songdragon.zboschina.proxy.ProxyHost;
import cn.songdragon.zboschina.proxy.ProxyManager;

public class ProxyFlightCrawler implements IFlightCrawler {

	private static final Logger logger = LoggerFactory.getLogger(ProxyFlightCrawler.class);

	private ProxyManager proxyManager;
	private HttpClient httpClient;
	private int maxTries = 6;

	public String queryFlight(String url, Map<String, String> headers) {
		return queryFlight(url, headers, null);
	}

	public String queryFlight(String url, Map<String, String> headers, IRefererGenerator refererGenerator) {

		int currentTry = 0;
		String result = "";
		while (currentTry < maxTries) {
			try {
				ProxyHost proxy = proxyManager.getAvaliableProxy();
				// System.out.println("Using proxy:" + proxy);

				HttpClientContext context = HttpClientContext.create();
				if (proxy != null) {
					//动态使用代理，通过构造RequestConfig.custom().setProxy
					RequestConfig config = RequestConfig.custom().setProxy(proxy.getProxy()).setSocketTimeout(5 * 1000)
							.setConnectTimeout(5 * 1000).build();

					context.setRequestConfig(config);
					if (headers != null && headers.size() != 0) {
						String referer = headers.get(HttpHeaders.REFERER);
						if (referer == null || referer.isEmpty()) {
							headers.put(HttpHeaders.REFERER, refererGenerator.getReferer(url));
						}
					}
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					HttpResponse response = httpClient.getHttpResponse(url, context, headers);
					if (response.getStatus() == HttpStatus.SC_OK
							|| response.getStatus() == HttpStatus.SC_NOT_MODIFIED) {
						logger.info("Response Header=" + response.getStatus());
						result = response.getBody();
						if (result.contains("MU")) {
							// proxyManager.resetProxyFailCount(proxy);
							// proxyManager.setProxyUseful(proxy);
							proxyManager.returnProxy(proxy, config, true);
							break;
						} else {
							// proxyManager.setProxyAsFail(proxy);
							proxyManager.returnProxy(proxy, config, false);
						}

					} else {
						logger.info("Proxy fail" + proxy);
						logger.info("Response Header=" + response.getStatus());
						// proxyManager.setProxyAsFail(proxy);
						proxyManager.returnProxy(proxy, config, false);
					}
				}

				currentTry++;
				if (currentTry < this.maxTries) {
					Random random = new Random(System.currentTimeMillis());

					int waitSeconds = random.nextInt((int) Math.pow(2, currentTry + 1));
					try {
						Thread.sleep(waitSeconds * 1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						// e.printStackTrace();
					}
				}
			} catch (NoProxyException npe) {
				logger.error("Please check proxy configuration");
				currentTry = currentTry + 2; // exit loop
				// System.exit(1);
			}

		}
		return result;
	}

	public ProxyManager getProxyManager() {
		return proxyManager;
	}

	public void setProxyManager(ProxyManager proxyManager) {
		this.proxyManager = proxyManager;
	}

	public HttpClient getHttpClient() {
		return httpClient;
	}

	public void setHttpClient(HttpClient httpClient) {
		this.httpClient = httpClient;
	}

}
